﻿using AsmShaderConverter.AsmShader;
using AsmShaderConverter.HlslShader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AsmShaderConverter.AsmFunctions
{
    public class AsmFunctionCmp : IConvertToHlsl
    {
        readonly string originalLineOfCode;
        private Register destination;
        private Register source1;
        private Register source2;
        private Register source3;
        public Register GetDestinationRegister()
        {
            return this.destination;
        }

        public AsmFunctionCmp(string lineOfCode)
        {


            this.originalLineOfCode = lineOfCode;

            lineOfCode = lineOfCode.Replace(",", "");
            lineOfCode = lineOfCode.Trim();
            var values = lineOfCode.Split(' ');

            switch (values.Length)
            {
                case 5:
                    this.destination = new Register(values[1],Swizzle.StandardXYZW);
                    this.source1 = new Register(values[2], destination.swizzle);
                    this.source2 = new Register(values[3], destination.swizzle);
                    this.source3 = new Register(values[4], destination.swizzle);
                    break;
                default:
                    throw new Exception("Function can´t be converted! " + lineOfCode);
            }

        }

        public string ToHLSL(AsmShaderFile asmShader)
        {

            Swizzle.SetSwizzleLengthToDestination(this.destination, this.source1);
            Swizzle.SetSwizzleLengthToDestination(this.destination, this.source2);
            Swizzle.SetSwizzleLengthToDestination(this.destination, this.source3);

            //if (destination.swizzle.Length == 0)
            //{
            //    destination.swizzle = new char[] { 'x', 'y', 'z', 'w' };
            //}

            string[] swizzleSource1 = new string[destination.swizzle.Length];
            string[] swizzleSource2 = new string[destination.swizzle.Length];
            string[] swizzleSource3 = new string[destination.swizzle.Length];
            //bool registerS1HasNoSwizzle = false;
            //bool registerS2HasNoSwizzle = false;
            //bool registerS3HasNoSwizzle = false;
            // Copy destination swizzles to source when source registers are none.
            if (source1.swizzle.Length == 0)
            {
                for (int i = 0; i < destination.swizzle.Length; i++)
                {
                    swizzleSource1[i] = destination.swizzle[i].ToString();
                }
            }// Copy destination swizzles to source when source registers are none.
            if (source2.swizzle.Length == 0)
            {
                for (int i = 0; i < destination.swizzle.Length; i++)
                {
                    swizzleSource2[i] = destination.swizzle[i].ToString();
                }
            }// Copy destination swizzles to source when source registers are none.
            if (source3.swizzle.Length == 0)
            {
                for (int i = 0; i < destination.swizzle.Length; i++)
                {
                    swizzleSource3[i] = destination.swizzle[i].ToString();
                }
            }


            // Soll die swizzles von der destination nehmen wenn keine originalen verfügbar sind.
            if (source1.swizzle.Length > 0)
                for (int i = 0; i < destination.swizzle.Length; i++)
                {
                    swizzleSource1[i] = source1.swizzle[Math.Min(i, source1.swizzle.Length - 1)].ToString();
                }
            // Soll die swizzles von der destination nehmen wenn keine originalen verfügbar sind.
            if (source2.swizzle.Length > 0)
                for (int i = 0; i < destination.swizzle.Length; i++)
                {
                    swizzleSource2[i] = source2.swizzle[Math.Min(i, source2.swizzle.Length - 1)].ToString();
                }
            // Soll die swizzles von der destination nehmen wenn keine originalen verfügbar sind.
            if (source3.swizzle.Length > 0)
                for (int i = 0; i < destination.swizzle.Length; i++)
                {
                    swizzleSource3[i] = source3.swizzle[Math.Min(i, source3.swizzle.Length - 1)].ToString();
                }

            StringBuilder sb = new StringBuilder();

            string countOfSwizzles = (this.destination.swizzle.Length > 2) ? "float" + this.destination.swizzle.Length.ToString() : string.Empty;
            sb.Append(string.Format("{0} = {1}(", this.destination.ToHLSL(asmShader), countOfSwizzles)); // start of block
            for (int i = 0; i < destination.swizzle.Length; i++)
            {
                sb.Append(String.Format("{0} < 0 ? {1} : {2}",

                    this.source1.GetNameWithNewSwizzle(swizzleSource1[i], asmShader),
                    this.source2.GetNameWithNewSwizzle(swizzleSource2[i], asmShader),
                    this.source3.GetNameWithNewSwizzle(swizzleSource3[i], asmShader)
                    ));
                if (i < destination.swizzle.Length - 1)
                    sb.Append(",\n");
            }
            sb.AppendLine(");");

            return sb.ToString();
        }

        public string ToHLSLWitchComment(AsmShaderFile asmShader)
        {
            return this.ToHLSL(asmShader) + "//" + this.originalLineOfCode;
        }
    }
}
